﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace MenuGame2DXNA
{
    /// <summary>
    /// Lớp cơ sở của các nhân vật trong game
    /// bao gồm các thuộc tính, phương thức di chuyển cũng như phương thức đăt bomb
    /// </summary>
    public abstract class Character : VisibleGameEntity
    {

        /// <summary>
        /// Gets or sets the ID.
        /// </summary>
        /// <value>
        /// The ID.
        /// </value>
        public int ID
        {
            get;
            set;

        }
        /// <summary>
        /// Gets or sets the tốc độ của nhân vật.
        /// Từ 1 đến 9
        /// </summary>
        /// <value>
        /// Tốc độ của nhân vật
        /// </value>
        private int _speeds;
        public int Speeds
        {
            get { return _speeds; }
            set 
            { 
                _speeds = value;
                foreach (UserControlledSprite us in ObjectVisible)
                {
                    us.Speeds = _speeds - 1;
                }
            }
        }

        /// <summary>
        /// Gets or sets the số mạng sống.
        /// </summary>
        /// <value>
        /// số mạng sống của nhân vật.
        /// </value>
        public short Lifes { get;  set; }

        /// <summary>
        /// Gets or sets the bomb bán kinh mà bom nổ.
        /// </summary>
        /// <value>
        /// Bán kính bom nổ.
        /// </value>
        public short BombRadius { get; set; }

        /// <summary>
        /// Gets or sets the n bomb allow.
        /// </summary>
        /// <value>
        /// số quả bom tối đa cho phép đặt của nhân vật
        /// </value>
        public short nBombAllow { get; set; }

        /// <summary>
        /// Gets or sets the điểm số nhân vật.
        /// </summary>
        /// <value>
        /// Điểm số của nhân vật
        /// </value>
        public short Score { get; set; }

        /// <summary>
        /// Gets or sets the kích thước mỗi ô.
        /// </summary>
        /// <value>
        /// kích thước mỗi ô trên bản đồ.
        /// </value>
        public Vector2 SizeCell { get; set; }


        private Point _pIndex;
        /// <summary>
        /// Gets or sets Vị trí trên ma trận bản đồ của nhân vật
        /// </summary>
        /// <value>
        /// Vị trí trên bản đồ của nhân vật
        /// </value>
        public Point pIndex
        {
            get { return _pIndex; }
            set {                
                _pIndex = value;
                PositionStart = Utilities.Index2Pixel(_pIndex);
            }
        }
        private int tick = 8;
        protected MOVEORIENT moveOrient;


        /// <summary>
        /// 
        /// </summary>
        protected sMainGame _mainGame;
  
        /// <summary>
        /// 
        /// </summary>
        private int times;

        private bool visible = true;

        public bool Visible
        {
            get { return visible; }
            set { visible = value; }
        }

        /// <summary>
        /// Khoảng cách mỗi lần di chuyển
        /// </summary>
        private bool death;

        public bool Death
        {
            get { return death; }
            set { death = value; }
        }
            
        private const int distance = 5;

        /// <summary>
        /// Gets or sets a value indicating whether [move flag].
        /// 
        /// </summary>
        /// <value>
        ///   <c>true</c> if [move flag]; otherwise, <c>false</c>.
        /// </value>

        //Định nghĩa gọi các hàm sự kiện nhân vật chết
        public delegate void Death_handle(object sender);
        public event Death_handle death_event;


        public bool MoveFlag { get; set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="Character"/> class.
        /// </summary>
        /// <param name="content">The content.</param>
        /// <param name="strTexture">The STR texture.</param>
        /// <param name="nTextures">The n textures.</param>
        /// <param name="topleft">The topleft.</param>
        /// <param name="size">The size.</param>
         protected Character(ContentManager content, string[] strTexture, int nTextures, Vector2 topleft, Vector2 size)
        {         
            InitCharacter(content, strTexture, nTextures, ref topleft, ref size);
        }

        
         /// <summary>
         /// Inits the enemy.
         /// </summary>
         /// <param name="content">The content.</param>
         /// <param name="strTexture">The STR texture.</param>
         /// <param name="nTextures">The n textures.</param>
         /// <param name="topleft">The topleft.</param>
         /// <param name="size">The size.</param>
         private void InitCharacter(ContentManager content, string[] strTexture, int nTextures, ref Vector2 _positionStart, ref Vector2 size)
        {
            TopLeft = new Vector2(0,0);
            PositionStart = _positionStart;
            Size = size;
            Texture2D[] textures = new Texture2D[nTextures];

            for (int i = 0; i < nTextures; i++)
                textures[i] = content.Load<Texture2D>(strTexture[i]);

            ObjectVisible = new List<UserControlledSprite>();
            UserControlledSprite tempSprite = new UserControlledSprite(textures, PositionStart);
            tempSprite.Size = size;

            ObjectVisible.Add(tempSprite);
            nObjectVisible = 1;
            MoveFlag = false;
            Speeds = 7;
            times = 0;
            moveOrient = MOVEORIENT.NONE;
            death = false;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Character"/> class.
        /// </summary>
        /// <param name="content">The content.</param>
        /// <param name="strTexturePreFix">The STR texture pre fix.</param>
        /// <param name="nTextures">The n textures.</param>
        /// <param name="topleft">The topleft.</param>
        /// <param name="size">The size.</param>
        protected Character(ContentManager content, string strTexturePreFix, int nTextures, Vector2 topleft, Vector2 size,sMainGame mainGame)
        {
            _mainGame = mainGame;
            string[] strTexture = new string[nTextures];
            for (int i = 0; i < nTextures; i++)
                strTexture[i] = strTexturePreFix + (i + 1).ToString("00");          
            InitCharacter(content, strTexture, nTextures, ref topleft, ref size);

        }



        /// <summary>
        /// Di chuyển tùy thích
        /// </summary>
        /// <param name="x">The x.</param>
        /// <param name="y">The y.</param>
        /// <param name="orient">The orient.</param>
        public void Move(int x , int y,MOVEORIENT orient,short frameStart, short FrameEnd)
        {
            
                if (MoveFlag == false)
                {
                    MoveFlag = true;
                    moveOrient = orient;
                }
                if (MoveFlag)
                {
                    if (times == 0)
                        ObjectVisible[0].SetFrame(frameStart, FrameEnd);
                    times++;
                  if (times %(10 - Speeds) == 0)

                      PositionStart = new Vector2(PositionStart.X + x, PositionStart.Y + y);
                    
                    if (times >= (SizeCell.X / distance) * (10 - Speeds))
                    {
                        MoveFlag = false;
                        times = 0;
                        ObjectVisible[0].Stop = true;
                        moveOrient = MOVEORIENT.NONE;
                        pIndex = Utilities.Pixel2Index(PositionStart);
                        int result = _mainGame.bootyManager.RemoveCell(pIndex);
                        switch (result)
                        { 
                            case 1:
                                BombRadius++;
                                SoundManager.Play("item");
                                break;
                            case 2:
                                Score += 100;
                                SoundManager.Play("item");
                                break;
                            case 3:
                                Lifes++;
                                SoundManager.Play("item");
                                break;
                            case 4:
                                nBombAllow++;
                                SoundManager.Play("item");
                                break;
                        }
                    }


                }
            
        }
        /// <summary>
        /// Di chuyển sang trái
        /// </summary>
        /// <param name="pIndexEnd">The p index end.</param>
        public virtual void MoveLeft(bool Auto)
        {
            if ((!Auto &&  moveOrient == MOVEORIENT.NONE) || (Auto && moveOrient == MOVEORIENT.MOVELEFT))
            
                Move(-distance, 0, MOVEORIENT.MOVELEFT, 15, 19);
            
        }
        /// <summary>
        /// Di chuyển sang phải
        /// </summary>
        /// <param name="pIndexEnd">The p index end.</param>
        public virtual void MoveRight(bool Auto)
        {
            if ((!Auto && moveOrient == MOVEORIENT.NONE) || (Auto && moveOrient == MOVEORIENT.MOVERIGHT))
            
            Move(distance, 0, MOVEORIENT.MOVERIGHT,0,4);
        }
        /// <summary>
        /// Di chuyển lên trên
        /// </summary>
        /// <param name="pIndexEnd">The p index end.</param>
        public virtual void MoveUp(bool Auto)
        {
            if ((!Auto && moveOrient == MOVEORIENT.NONE) || (Auto && moveOrient == MOVEORIENT.MOVEUP))
            
            Move(0, -distance, MOVEORIENT.MOVEUP,10,14);
        }
        /// <summary>
        /// Di chuyển xuống dưới
        /// </summary>
        /// <param name="pIndexEnd">The p index end.</param>
        public virtual void MoveDown(bool Auto)
        {
            if ((!Auto && moveOrient == MOVEORIENT.NONE) || (Auto && moveOrient == MOVEORIENT.MOVEDOWN))
            
            Move(0, distance, MOVEORIENT.MOVEDOWN,5,9);
        }
        

       

        public enum MOVEORIENT { MOVERIGHT = 0, MOVEDOWN, MOVEUP, MOVELEFT, NONE };


        /// <summary>
        /// Phương thức đặt bomb
        /// </summary>
        public  virtual void AddBomb(GameTime gameTime)
        {
            
        }
    
        /// <summary>
        /// Destroys the specified game time.
        /// </summary>
        /// <param name="gameTime">The game time.</param>
        public virtual void Destroy()
        {
            if (tick > 7 && visible)
            {
               
                ObjectVisible[0].SetFrame(20, 26);
                Lifes--;
                tick = 0;
                SoundManager.Play("death");
                if(Lifes<0)
                {
                    Lifes = 0;
                    death = true;
                    if(death_event !=null)
                     death_event(this);
                }
            }
        }
        
        public virtual void Win()
        {
            moveOrient = MOVEORIENT.NONE;
            ObjectVisible[0].SetFrame(27, 32);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="Character"/> class.
        /// </summary>
        protected Character()
        {

        }
        /// <summary>
        /// Updates the specified game time.
        /// </summary>
        /// <param name="gameTime">The game time.</param>
        /// <param name="color">The color.</param>
        public override void Update(GameTime gameTime, Color color)
        {
            tick++;
            if(tick == 7)
                visible = false;
            if (tick == 100 && !visible && !death)
            {
                ObjectVisible[0].SetFrame(5, 5);
                visible = true;
                SoundManager.Play("ready");
            }
            base.Update(gameTime, color);
        }
        public override void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            if (visible)
            {
                base.Draw(gameTime, spriteBatch);
            }
            
            
        }

    }
}
